package com.moli.iov.util;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.apache.commons.lang.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 功能说明：pdf文档转图片 第三方依赖：pdfbox-2.0.8.jar <dependency>
 * <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId>
 * <version>2.0.8</version> </dependency>
 *
 * @return <br/>
 *         修改历史：<br/>
 *         1.[2018年01月08日 上午11:56] 创建方法 by guyi
 */
public class PdfToImageUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(PdfToImageUtil.class);

	private static final String PAGE_INDEX_SEPARATOR = ",";
	private static final String DOT = ".";

	/**
	 * pdf转图片(png图片)
	 * 
	 * @param srcFile
	 *            pdf转换源文件
	 * @throws IOException
	 */
	public static String pdfToImage(String srcFile) throws IOException {
		pdfToImage(srcFile, null, null, null, null, true);
		return srcFile.substring(0, srcFile.lastIndexOf(DOT)) + DOT + "png";
	}

	/**
	 * pdf转图片
	 * 
	 * @param srcFile
	 *            pdf转换源文件
	 * @param imgName
	 *            图片名称，为空时默认源文件名称_001
	 * @param format
	 *            待输出图片的格式，默认png
	 * @throws IOException
	 */
	public static String pdfToImage(String srcFile, String imgName, String format) throws IOException {
		pdfToImage(srcFile, null, imgName, format, null, true);
		return srcFile.substring(0, srcFile.lastIndexOf(DOT)) + DOT + (StringUtils.isBlank(format) ? "png" : format);
	}

	/**
	 * pdf转图片
	 * 
	 * @param srcFile
	 *            pdf转换源文件
	 * @param destPath
	 *            图片输出目标路径，为空时默认源文件所在的文件夹
	 * @param imgName
	 *            图片名称，为空时默认源文件名称_001
	 * @param format
	 *            待输出图片的格式，默认png
	 * @param dpi
	 *            分辨率，默认96
	 * @param merge
	 *            是否合并为一张，默认为每页生成一张图片
	 * @throws IOException
	 */
	public static void pdfToImage(String srcFile, String destPath, String imgName, String format, Float dpi,
			Boolean merge) throws IOException {
		File file = new File(srcFile);
		// 默认输出路径为源文件所在文件夹
		if (destPath == null || destPath.isEmpty()) {
			destPath = file.getParent();
		}
		List<BufferedImage> images = pdfToImage(file, dpi == null ? 96f : dpi);
		if (images == null || images.isEmpty()) {
			return;
		}
		// 默认为jpg
		format = format == null || format.isEmpty() ? "png" : format;
		if (StringUtils.isBlank(imgName)) {
			String pdfFileName = file.getName();
			imgName = pdfFileName.substring(0, pdfFileName.indexOf('.'));
		}
		StringBuilder sb = new StringBuilder();
		// 合并多张图片为一张
		merge = merge == null ? false : merge;
		if (merge) {
			BufferedImage image = mergeImages(images);
			images.clear();
			images.add(image);
		}

		// 保存到本地
		for (int i = 0, len = images.size(); i < len; i++) {
			// 输出格式: [文件夹路径]/[pdf文件名]_0001.jpg
			if (i == 0) {
				ImageIO.write(images.get(i), format, new File(sb.append(destPath).append(File.separator).append(imgName)
						.append(".").append(format).toString()));
			} else {
				ImageIO.write(images.get(i), format, new File(sb.append(destPath).append(File.separator).append(imgName)
						.append("_").append(String.format("%04d", i + 1)).append(".").append(format).toString()));
			}

			sb.setLength(0);
		}
	}

	private static BufferedImage mergeImages(List<BufferedImage> images) {
		int width = 0, height = 0;
		for (BufferedImage image : images) {
			width = image.getWidth() > width ? image.getWidth() : width;
			height += image.getHeight();
		}
		BufferedImage pdfImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2d = pdfImage.createGraphics();
		height = 0;
		for (BufferedImage image : images) {
			g2d.drawImage(image, (width - image.getWidth()) / 2, height, image.getWidth(), image.getHeight(), null);
			height += image.getHeight();
		}
		g2d.dispose();
		return pdfImage;
	}

	private static List<BufferedImage> pdfToImage(File file, float dpi) throws IOException {
		List<BufferedImage> imgList = null;
		PDDocument pdDocument = null;
		BufferedImage image;
		try {
			pdDocument = PDDocument.load(file);
			PDFRenderer renderer = new PDFRenderer(pdDocument);
			int numPages = pdDocument.getNumberOfPages();
			imgList = new ArrayList<BufferedImage>();
			for (int i = 0; i < numPages; i++) {
				image = renderer.renderImageWithDPI(i, dpi);
				if (null != image) {
					imgList.add(image);
				}
			}
		} catch (IOException e) {
			LOGGER.error("convert pdf pages to images failed.", e);
			// FIXME
			throw e;
		} finally {
			try {
				if (null != pdDocument) {
					pdDocument.close();
				}
			} catch (IOException e) {
				LOGGER.error("close IO failed when convert pdf pages to images.", e);
				// FIXME
				throw e;
			}
		}
		return imgList;
	}

}